home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 2000 November: Tool Chest / Dev.CD Nov 00 TC Disk 1.toast / What's New? / Development Kits / Mac OS / USB DDK 1.4.6f4 / Examples / KeyboardModule / KBDHIDEmulation.c < prev    next >
Encoding:
C/C++ Source or Header  |  2000-09-25  |  8.7 KB  |  310 lines  |  [TEXT/MPS ]

  1. /*
  2.     File:        KBDHIDEmulation.c
  3.  
  4.     Contains:    Keyboard Emulation code
  5.  
  6.     Version:    xxx put version here xxx
  7.  
  8.     Copyright:    © 1998-2000 by Apple Computer, Inc., all rights reserved.
  9.  
  10. */
  11.  
  12. #include <Devices.h>
  13. #include <DriverServices.h>
  14. #include <CodeFragments.h>
  15. #include <MacTypes.h>
  16. #include <USB.h>
  17.  
  18. #ifndef DDKBuild
  19.     #include <USBPriv.h>
  20. #endif
  21.  
  22. #include "KeyboardModule.h"
  23.  
  24. #define CFM_AddressIsResolved_(addr)    ((addr) != (void*) kUnresolvedCFragSymbolAddress)
  25.  
  26. extern    usbKeyboardPBStruct myKeyboardPB;
  27. extern    usbKeyboardPBStruct shimKeyboardPB;
  28.  
  29. void GetKeysPressed(USBHIDData * pKeysPressed);
  30.  
  31. OSStatus USBHIDInstallInterrupt(HIDInterruptProcPtr HIDInterruptFunction, UInt32 refcon)
  32. {
  33.     myKeyboardPB.interruptRefcon = refcon;
  34.     myKeyboardPB.pSHIMInterruptRoutine = HIDInterruptFunction;
  35.     return 0;
  36. }
  37.  
  38. OSStatus USBHIDControlDevice(UInt32 theControlSelector, void * theControlData)
  39. {
  40.     switch (theControlSelector)
  41.     {
  42.         case kHIDSetLEDStateByBits:
  43.             if (shimKeyboardPB.keyboardReady)
  44.             {
  45.                 shimKeyboardPB.keyboardReady = false;    // Don't do this again before it completes
  46.                 shimKeyboardPB.hidReport[0] = *(UInt8*)theControlData;
  47.     
  48.                 shimKeyboardPB.retryCount = 3;
  49.                 shimKeyboardPB.delayLevel = 0;                            
  50.                 shimKeyboardPB.transDepth = 0;    
  51.                 
  52.                 shimKeyboardPB.pb.usbRefcon = kSetKeyboardLEDs;                    /* Start with setting the interface protocol */
  53.                 KeyboardInitiateTransaction(&shimKeyboardPB.pb);
  54.             }
  55.             else
  56.             {
  57.                 USBExpertStatus(myKeyboardPB.interfaceRef, kKeyboardModuleName": Set LED request when keyboard is busy", myKeyboardPB.interfaceRef);
  58.                 return kUSBDeviceBusy;
  59.             }
  60.             break;
  61.             
  62.         case kHIDRemoveInterruptHandler:
  63.             myKeyboardPB.interruptRefcon = nil;
  64.             myKeyboardPB.pSavedInterruptRoutine = nil;
  65.             myKeyboardPB.pSHIMInterruptRoutine = nil;
  66.             break;
  67.             
  68.         case kHIDEnableDemoMode:
  69.             USBExpertStatus(myKeyboardPB.interfaceRef, kKeyboardModuleName": Demo Mode Enabled", myKeyboardPB.interfaceRef);
  70.             InitUSBKeyboard();
  71.             myKeyboardPB.pSavedInterruptRoutine = myKeyboardPB.pSHIMInterruptRoutine;
  72.             myKeyboardPB.pSHIMInterruptRoutine = USBDemoKeyIn;
  73.             break;
  74.  
  75.         case kHIDDisableDemoMode:
  76.             USBExpertStatus(myKeyboardPB.interfaceRef, kKeyboardModuleName": Demo Mode Disabled", myKeyboardPB.interfaceRef);
  77.             myKeyboardPB.pSHIMInterruptRoutine = myKeyboardPB.pSavedInterruptRoutine;
  78.             break;
  79.  
  80.         default:
  81.             return paramErr;
  82.     }
  83.     return 0;
  84. }
  85.  
  86. void GetKeysPressed(USBHIDDataPtr pKeysPressed)
  87. {
  88. UInt8    i,keycount;
  89.     
  90.     keycount = 0;
  91.     for (i = 0; i < kKeyboardModifierBits; i++)
  92.     {
  93.         if (myKeyboardPB.oldHIDReport[0] & (1 << i))
  94.         {
  95.             pKeysPressed->kbd.usbkeycode[keycount++] = (0xe0 + i);
  96.         }
  97.     }
  98.             
  99.     if ((myKeyboardPB.oldHIDReport[kKeyboardOffsetToKeys] == 0) || (myKeyboardPB.oldHIDReport[kKeyboardOffsetToKeys] > 0x03))
  100.     {
  101.         for (i = kKeyboardOffsetToKeys; i < (kKeyboardOffsetToKeys + kKeyboardReportKeys); i++)
  102.         {
  103.             if (myKeyboardPB.oldHIDReport[i] > 0x03)
  104.             {
  105.                 pKeysPressed->kbd.usbkeycode[keycount++] = myKeyboardPB.oldHIDReport[i];
  106.             }
  107.         }                                                        
  108.     }
  109.     pKeysPressed->kbd.keycount = keycount;
  110. }
  111.  
  112.  
  113. OSStatus USBHIDGetDeviceInfo(UInt32 theInfoSelector, void * theInfo)
  114. {
  115. HIDInterruptProcPtr * pHIDIntProcPtr;
  116. UInt32 * pInterruptRefcon;
  117.  
  118.     switch (theInfoSelector)
  119.     {
  120.         case kHIDGetCurrentKeys:
  121.             GetKeysPressed((USBHIDDataPtr)theInfo);
  122.             break;
  123.  
  124.         case kHIDGetInterruptHandler:
  125.             pHIDIntProcPtr = (HIDInterruptProcPtr *)theInfo;  
  126.             *pHIDIntProcPtr = myKeyboardPB.pSHIMInterruptRoutine;
  127.             break;
  128.  
  129.         case kHIDGetInterruptRefcon:
  130.             pInterruptRefcon = (UInt32 *)theInfo;
  131.             *pInterruptRefcon = myKeyboardPB.interruptRefcon;
  132.             break;
  133.         
  134.         default:
  135.             return paramErr;
  136.     }
  137.     return 0;
  138. }
  139.  
  140. OSStatus USBHIDPollDevice(void)
  141. {
  142. #ifndef DDKBuild
  143.     USLPolledProcessDoneQueue();
  144. #endif
  145.     return kUSBNoErr;
  146. }
  147.  
  148. OSStatus USBHIDEnterPolledMode(void)
  149. {    
  150. #ifndef DDKBuild
  151.     USBExpertStatus(myKeyboardPB.interfaceRef, kKeyboardModuleName": Entering Polled Mode: ", 0);
  152.     if ( CFM_AddressIsResolved_(USLDebuggerActive) )
  153.         USLDebuggerActive( true );
  154. #endif
  155.     return kUSBNoErr;
  156. }
  157.  
  158. OSStatus USBHIDExitPolledMode(void)
  159. {
  160. #ifndef DDKBuild
  161.     USBExpertStatus(myKeyboardPB.interfaceRef, kKeyboardModuleName": Exiting Polled Mode: ", 0);
  162.     if ( CFM_AddressIsResolved_(USLDebuggerActive) )
  163.         USLDebuggerActive( false );
  164. #endif
  165.     return kUSBNoErr;
  166. }
  167.  
  168. void NotifyRegisteredHIDUser(UInt32 devicetype, UInt8 hidReport[])
  169. {
  170. #pragma unused (devicetype)
  171. static    UInt8    keydebug = 0;
  172.  
  173. UInt8    i, j, newkey, oldkey, deltas;
  174.  
  175. UInt8        changedmodifiers, keycount;
  176. USBHIDData    theKeyboardData;
  177. Boolean        keypressedflag, keyreleasedflag;
  178.     
  179.     deltas = 0;
  180.     
  181.     if (myKeyboardPB.hidEmulationInit == false)
  182.     {
  183.         myKeyboardPB.hidEmulationInit = true;
  184.         for (i = 0; i < kKeyboardReportSize; i++)
  185.             myKeyboardPB.oldHIDReport[i] = 0;
  186.     };
  187.     
  188.     myKeyboardPB.oldHIDReport[1] = 0x0;
  189.     hidReport[1] = 0x0;
  190.     
  191.     for (i = 0; i < kKeyboardReportSize; i++)
  192.     {
  193.         if (hidReport[i] != myKeyboardPB.oldHIDReport[i])
  194.         {
  195.             deltas++;
  196.         }
  197.     }
  198.     
  199.     if ((myKeyboardPB.sendRawReportFlag) && deltas)
  200.     {
  201.         (*myKeyboardPB.pSHIMInterruptRoutine)(0xff, (void *)&hidReport[0]);
  202.     }
  203.     else
  204.     {
  205.         if (deltas)
  206.         {
  207.             keycount = 0;
  208.             changedmodifiers = hidReport[0] ^  myKeyboardPB.oldHIDReport[0];
  209.             
  210.             if (changedmodifiers)
  211.             {
  212.                 for (i = 0; i < kKeyboardModifierBits; i++)
  213.                 {
  214.                     if (changedmodifiers & (1 << i))
  215.                     {
  216.                         if (hidReport[0] & (1 << i))
  217.                         {
  218.                             if (keydebug++ < 8)
  219.                             {
  220.                                 USBExpertStatus(myKeyboardPB.interfaceRef, kKeyboardModuleName": Modifier key pressed: ", (0xe0 + i));
  221.                             }
  222.                             theKeyboardData.kbd.usbkeycode[keycount++] = (0xe0 + i);
  223.                         }
  224.                         else
  225.                         {
  226.                             if (keydebug++ < 8)
  227.                             {
  228.                                 USBExpertStatus(myKeyboardPB.interfaceRef, kKeyboardModuleName": Modifier key released:", (0xe0 + i));
  229.                             }
  230.                             theKeyboardData.kbd.usbkeycode[keycount++] = (0x80e0 + i);
  231.                         }
  232.                     }
  233.                 }
  234.                 myKeyboardPB.oldHIDReport[0] = hidReport[0];
  235.             }
  236.             
  237.             if ((hidReport[kKeyboardOffsetToKeys] == 0) || (hidReport[kKeyboardOffsetToKeys] > 0x03))
  238.             {
  239.                 // While this double loop may look strange, I refer you to appendix C, of the HID Devices specification.
  240.                 // pp. 73 & 74 clearly state that report order is abitrary and does not reflect the order of events.
  241.                 // to quote: "The order of keycodes in array fields has no significance.  Order determination is done
  242.                 // by the host software comparing the contents of the previous report to the current report.  If two or 
  243.                 // more keys are pressed in one report, their order is indeterminate.  Keyboards may buffer events that
  244.                 // would have otherwise resulted in multiple events in a single report".
  245.                 
  246.                 // Because this specification (or lack thereof) states that the order is indeterminant, we have to 
  247.                 // check all the old keys against all the new keys...
  248.                 
  249.                 for (i = kKeyboardOffsetToKeys; i < (kKeyboardOffsetToKeys + kKeyboardReportKeys); i++)
  250.                 {
  251.                     keypressedflag = true;
  252.                     newkey = hidReport[i];
  253.                     
  254.                     keyreleasedflag = true;
  255.                     oldkey = myKeyboardPB.oldHIDReport[i];                            
  256.                     for (j = kKeyboardOffsetToKeys; j < (kKeyboardOffsetToKeys + kKeyboardReportKeys); j++)                                // then look through all the keys that were previously and are currently reported as pressed
  257.                     {                                    
  258.                         if (newkey == myKeyboardPB.oldHIDReport[j])        // was this new key already pressed?
  259.                         {                                
  260.                             keypressedflag = false;                        // if it was, then don't report it as being pressed.
  261.                         }
  262.                         
  263.                         if (oldkey == hidReport[j])                        // Is the old key still pressed?
  264.                         {                                
  265.                             keyreleasedflag = false;                    // If yes, then don't report it as being released
  266.                         }
  267.                     }
  268.                     if ((newkey > 0x03) && keypressedflag)
  269.                     {
  270.                         theKeyboardData.kbd.usbkeycode[keycount++] = newkey;
  271.                     }
  272.                     
  273.                     if ((oldkey > 0x03) && keyreleasedflag)
  274.                     {
  275.                         theKeyboardData.kbd.usbkeycode[keycount++] = (oldkey + 0x8000);
  276.                     }
  277.                     
  278.                     if (keycount > 20)                                    // a worse case scenario is:
  279.                     {                                                    // 4 modifier keys up
  280.                         break;                                            // the other 4 modifier keys down
  281.                     }                                                    // 6 previously reported keys up
  282.                 }                                                        // 6 newly reported keys down
  283.                                                                         // 6 + 6 + 4 + 4 = 20
  284.                 for (i = 0; i<kKeyboardReportSize; i++)
  285.                 {
  286.                     myKeyboardPB.oldHIDReport[i] = hidReport[i];
  287.                 };
  288.             }
  289.             
  290.             if ((myKeyboardPB.pSHIMInterruptRoutine) && keycount)
  291.             {
  292.                 theKeyboardData.kbd.keycount = keycount;
  293.                 (*myKeyboardPB.pSHIMInterruptRoutine)(myKeyboardPB.interruptRefcon, (void *)&theKeyboardData);
  294.             }
  295.         }
  296.     }
  297. }
  298.  
  299.  
  300. USBHIDModuleDispatchTable TheHIDModuleDispatchTable =
  301. {
  302.     (UInt32)kHIDStandardDispatchVersion,
  303.     (USBHIDInstallInterruptProcPtr)USBHIDInstallInterrupt,
  304.     (USBHIDPollDeviceProcPtr)USBHIDPollDevice,
  305.     (USBHIDControlDeviceProcPtr)USBHIDControlDevice,
  306.     (USBHIDGetDeviceInfoProcPtr)USBHIDGetDeviceInfo,
  307.     (USBHIDEnterPolledModeProcPtr)USBHIDEnterPolledMode,
  308.     (USBHIDExitPolledModeProcPtr)USBHIDExitPolledMode,
  309. };
  310.